﻿/************************************************************************

   Extended Silverlight Toolkit

   Copyright (C) 2010-2012 Xceed Software Inc.

   This program is provided to you under the terms of the Microsoft Public
   License (Ms-PL) as published at http://extendedsilverlight.codeplex.com/license

   Please purchase a commercial version of this toolkit if you are using
   it in a commercial product. The commercial versions support the project,
   and also include more features for each control, priority support,
   source code, updates, removed watermark, and a proprietary license.

   Visit http://xceed.com and follow @datagrid on Twitter.

  **********************************************************************/

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Text;
using System.Globalization;
using System.Collections.Generic;
using System.Diagnostics;

namespace Xceed.Silverlight.Data
{
  internal class DebugLogManager
  {
    private const string NullString = "(null)";
    private static Dictionary<string, int> Ids = new Dictionary<string, int>();
    private int m_commentDepth = 0;

    public DebugLogManager(string className, Action<string> logger)
    {
      if( className == null )
        throw new ArgumentNullException( "className" );

      m_logger = logger;
      if(!DebugLogManager.Ids.ContainsKey(className))
      {
        DebugLogManager.Ids.Add(className,0);
      }
      m_childClassName = string.Format( "{0}[{1}]", className, DebugLogManager.Ids[ className ]++ );
    }


    public void LogBefore( string callName, params object[] args )
    {
      DoLog( LogType.Before, callName, null, args );
    }

    public void LogAfter( string callName, params object[] args )
    {
      DoLog( LogType.After_, callName, null, args );
    }

    public void LogSingle( string callName, params object[] args )
    {
      DoLog( LogType.Single, callName, null, args );
    }

    public void LogR( string callName, object ret, params object[] args )
    {
      DoLog( LogType.Return, callName, ( ret == null ) ? NullString : ret, args );
    }

    private void DoLog( LogType logType, string callName, object ret, params object[] args )
    {
      if( m_logger == null )
        return;

      string logTypeStr;
      if( logType == LogType.Return )
      {
        logTypeStr = "----->";
      }
      else
      {
        logTypeStr = logType.ToString();
      }

      string log;
      if( args.Length > 0 )
      {
        StringBuilder sb = new StringBuilder();
        for( int i = 0; i < args.Length; i++ )
        {
          sb.Append( args[ i ] == null ? NullString : args[ i ].ToString() );
          if( args.Length - 1 > i )
          {
            sb.Append( "," );
          }
        }
        string formatStr = ( ret == null ) ? "{4} :{0}.{1}({2})" : "{4} :{0}.{1}({2}) ret={3}";
        log = string.Format( CultureInfo.InvariantCulture, formatStr, m_childClassName, callName, sb.ToString(), ret, logTypeStr );
      }
      else
      {
        string formatStr = ( ret == null ) ? "{3} :{0}.{1}" : "{3} :{0}.{1}, ret={2}";
        log = string.Format( CultureInfo.InvariantCulture, formatStr, m_childClassName, callName, ret, logTypeStr );
      }

      if( logType == LogType.After_ )
      {
        Debug.Assert( m_commentDepth > 0 );
        m_commentDepth--;
      }

      StringBuilder totalLog = new StringBuilder( m_commentDepth * 2 + log.Length );
      totalLog.Append( ' ', m_commentDepth * 2 );
      totalLog.Append( log );

      if( logType == LogType.Before )
      {
        m_commentDepth++;
      }
      else if( logType == LogType.Return )
      {
        Debug.Assert( m_commentDepth > 0 );
        m_commentDepth--;
      }


      m_logger( totalLog.ToString() );
    }

    private Action<string> m_logger;
    private string m_childClassName;


    private enum LogType
    {
      Single,
      Before,
      After_,
      Return
    }

  }
}
